package com.tangruojie.filter;

import com.alibaba.fastjson2.JSON;
import com.tangruojie.constant.RedisConstant;
import com.tangruojie.service.impl.UserDetailsImpl;
import com.tangruojie.utils.JwtUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * JWT 认证后的流程
 * 请求头带：Authorization: Bearer xxx
 * 进入 JwtAuthenticationFilter：
 * 解析 token，拿到 userId、角色信息。
 * 封装成 UsernamePasswordAuthenticationToken（已认证 = true）。
 * 塞进 SecurityContextHolder。
 * 后续接口调用时：
 * FilterSecurityInterceptor 拿出 Authentication，发现有角色 ROLE_ADMIN，就能通过 .hasRole("ADMIN") 校验。
 */
@Component
@RequiredArgsConstructor
public class LoginOncePerRequestFilter extends OncePerRequestFilter {

    public final JwtUtils jwtUtils;

    public final StringRedisTemplate stringRedisTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader(RedisConstant.TOKEN);
        if (!StringUtils.hasText(token)) {
            filterChain.doFilter(request, response);
            return; // 跳过当前过滤器
        }
        String id = jwtUtils.getId(token);
        if (!StringUtils.hasText(id)) {
            throw new RuntimeException("Token 错误！");
        }
        String information = stringRedisTemplate.opsForValue().get(RedisConstant.USER_TOKEN + id);
        UserDetailsImpl userDetails = JSON.parseObject(information, UserDetailsImpl.class);
        if (userDetails == null) {
            throw new RuntimeException("用户未登录！");
        }
        // 获取权限信息封装到Authentication中
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        filterChain.doFilter(request, response);
    }

}
